package ja12resttemplate.util;

import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONValidator;
import ja12resttemplate.util.AssertUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

public class RestFulUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(RestFulUtil.class);

    //常用参数变量
    //格式化：代替过期：MediaType.APPLICATION_JSON_UTF8
    public static final MediaType APPLICATION_JSON = new MediaType("application","json",StandardCharsets.UTF_8);
    public static final String APPLICATION_JSON_UTF8_VALUE = "application/json;charset=UTF-8";

    //json是否符合格式做认证
    public static boolean JsonValid(String jsonStr){
        JSONValidator validator = JSONValidator.from(jsonStr);
        return validator.validate();
    }

    //输出长度过长就限制为300个字符做输出
    public static String cutOut(JSONObject jsonObj) {
        String jsonStr = null;
        if(AssertUtil.isVal(jsonObj)) {
            String objStr = JSONObject.toJSONString(jsonObj);
            if(AssertUtil.isVal(objStr)){
                jsonStr = cutOut(objStr);
            }
        }
        return jsonStr;
    }

    //string，限制输出：300
    public static String cutOut(String origin){
        String strOut = null;
        if(AssertUtil.isVal(origin)){
            strOut = origin;
            if(origin.length()>300) {
                strOut = origin.substring(0, 299);
            }
        }
        return strOut;
    }

    //静态方法使用本项目中也配置了框架实体：RestConfig；本处使用静态
    private static final RestTemplate restTemplate = new RestTemplate();
    //解决：中文乱码，编码定义为：UTF-8
    static{
        if (AssertUtil.isVal(restTemplate.getMessageConverters())) {
            List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
            for (int i = 0; i < messageConverters.size(); i++) {
                HttpMessageConverter<?> httpMessageConverter = messageConverters.get(i);
                if (httpMessageConverter.getClass().equals(StringHttpMessageConverter.class)) {
                    messageConverters.set(i, new StringHttpMessageConverter(StandardCharsets.UTF_8));
                }
            }
        }
    }

    /**
     * url 格式化，并且处理空格问题
     * @param url 原地址
     * @return 处理后地址
     */
    public static String url4Encode(String url){
        String urlNew = url;
        try{
            String encode = URLEncoder.encode(url, StandardCharsets.UTF_8.toString());
            urlNew = encode.replaceAll("\\+", "%20");//解决问题:编码后空格会变成+号
        }catch (Exception e){
            LOGGER.error("格式化url地址报错："+e.getMessage());
        }
        return urlNew;
    }

    /**
     * get方式url拼接地址把参数拼接url
     * @param params 参数集合
     * @return 处理后地址
     */
    public static String map2params(Map<String,Object> params){
        String url = null;
        try{
            StringBuilder urlNew = new StringBuilder();
            urlNew.append("?");
            for(String key:params.keySet()){
                String value = String.valueOf(params.get(key));
                value = url4Encode(value);
                urlNew.append(key).append("=").append(value).append("&");
            }
            urlNew.delete(urlNew.length()-1,urlNew.length());//去掉最后一个&
            url = urlNew.toString();
        }catch (Exception e){
            LOGGER.error("格式化url地址报错："+e.getMessage());
        }
        return url;
    }

    /**
     * url和参数
     * @param url 地址
     * @param params 参数
     * @return get方式的拼接
     */
    public static String url4params(String url, Map<String,Object> params){
        return url + map2params(params);
    }

    /**
     * get方式，参数以map方式传入
     * @param url 地址
     * @param params 参数
     * @return 请求结果
     */
    public static JSONObject getForEntity(String url,Map<String,Object> params) {
        return getForEntity(url4params(url,params));
    }

    /**
     * restTemplate：get请求
     */
    public static JSONObject getForEntity(String url) {
        //RestTemplate restTemplate = new RestTemplate();//新创建
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(url,String.class);
        String jsonValue = responseEntity.getBody();
        JSONObject result = null;
        if (AssertUtil.isVal(jsonValue) && JsonValid(jsonValue)) {
            result = JSONObject.parseObject(jsonValue);
        }
        if(AssertUtil.isVal(result)) {
            String outStr = cutOut(result);
            LOGGER.info("restTemplate的get请求结果为："+outStr);
        }
        return result;
    }

    /**
     * restTemplate：get请求，设置httpHeaders
     */
    public static JSONObject getForEntityHeader(String url,Map<String,Object> params, HttpHeaders httpHeaders) {
        JSONObject result = null;
        try {
            if(AssertUtil.isVal(httpHeaders)){
                httpHeaders.setContentType(APPLICATION_JSON);
            }
            url = url4params(url,params);
            HttpEntity<Map<String,Object>> request = new HttpEntity<>(httpHeaders);
            ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.GET,request,String.class);
            String jsonValue = exchange.getBody();
            if (AssertUtil.isVal(jsonValue) && JsonValid(jsonValue)) {
                result = JSONObject.parseObject(jsonValue);
            }
            if (AssertUtil.isVal(result)) {
                String outStr = cutOut(result);
                LOGGER.info("restTemplate的get请求结果为：" + outStr);
            }
        }catch (Exception e){
            LOGGER.error("getForEntityHeader请求报错："+e.getMessage());
        }
        return result;
    }

    /**
     * restTemplate：put请求，设置httpHeaders
     */
    public static JSONObject putForEntityHeader(String url, HttpHeaders httpHeaders) {
        JSONObject result = null;
        try {
            if(AssertUtil.isVal(httpHeaders)){
                httpHeaders.add("Content-type", APPLICATION_JSON_UTF8_VALUE);
            }
            System.out.println("url==="+url);
            HttpEntity<Map<String,Object>> request = new HttpEntity<>(httpHeaders);
            ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.PUT,request,String.class);
            String jsonValue = exchange.getBody();
            LOGGER.info("jsonValue ：" + jsonValue);
            System.out.println("jsonValue ：" + jsonValue);
            if (JsonValid(jsonValue)) {
                result = JSONObject.parseObject(jsonValue);
            }
            LOGGER.info("restTemplate的put请求结果为：" + result);
        }catch (Exception e){
            LOGGER.error("putForEntityHeader请求报错："+e.getMessage(),e);
        }
        return result;
    }

    /**
     * restTemplate：post请求：json方式 带headers
     */
    public static JSONObject postForEntityHeadersJsonStr(String url, String jsonStr) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> request = new HttpEntity<>(jsonStr, headers);
        HttpEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
        String jsonValue = responseEntity.getBody();
        JSONObject result = null;
        if (AssertUtil.isVal(jsonValue) && JsonValid(jsonValue)) {
            result = JSONObject.parseObject(jsonValue);
        }
        if(AssertUtil.isVal(result)) {
            String outStr = cutOut(result);
            LOGGER.info("json字符串作为参数的restTemplate请求："+outStr);
        }
        return result;
    }

    /**
     * restTemplate：post请求：json方式 带headers
     * 若headers为null，也能调用
     * @param url 地址
     * @param httpBody 请求参数
     * @param httpHeaders 请求头
     * @return 返回结果
     */
    public static JSONObject postForEntityHeadersJson(String url, Map<String,Object> httpBody, HttpHeaders httpHeaders){
        JSONObject result = null;
        try {
            //LOGGER.info("postForEntityHeadersJsonBody:请求地址为："+url
            //        +"\n 参数数量为：" + (httpBody==null?null:httpBody.size())
            //        +"\n 表头数量为:" + (httpHeaders==null?null:httpHeaders.size())
            //);
            /*案例:表头，请求体是json
            //headers
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("Authorization","Bearer eyJhbGciOiJS...");
            //body-使用json
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);//此项可不填写
            Map<String, Object> httpBody = new HashMap<>();
            httpBody.put("id", 2L);
            httpBody.put("name", "requestBody-json");*/
            //httpEntity
            if(!AssertUtil.isVal(httpHeaders)){
                httpHeaders = new HttpHeaders();
            }
            httpHeaders.setContentType(APPLICATION_JSON);
            //httpHeaders.add("Content-type", APPLICATION_JSON_UTF8_VALUE);
            HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(httpBody, httpHeaders);
            ResponseEntity<String> responseEntity = restTemplate.postForEntity(url,httpEntity,String.class);
            String jsonValue = responseEntity.getBody();
            if (AssertUtil.isVal(jsonValue) && JsonValid(jsonValue)) {
                result = JSONObject.parseObject(jsonValue);
            }
            if(AssertUtil.isVal(result)) {
                String outStr = cutOut(result);
                LOGGER.info("post的RequestBody方式添加headers的非实体类json方式："+outStr);
            }
        } catch (RestClientException e) {
            LOGGER.error("POST调用【包含：httpBody和httpHeaders】：运行报错为："+e.getMessage());
        }
        return result;
    }

    /**
     * restTemplate：post请求：json方式【Map集合】
     * 若headers为null，也能调用
     * @param url 地址
     * @param httpBody 请求参数
     * @return 返回结果
     */
    public static JSONObject postForEntityHeadersJson(String url, Map<String,Object> httpBody){
        JSONObject result = null;
        try {
            /*案例:请求体是json：Map的方式
            Map<String, Object> httpBody = new HashMap<>();
            httpBody.put("id", 2L);
            httpBody.put("name", "requestBody-json");*/
            result = postForEntityHeadersJson(url,httpBody,null);
        } catch (RestClientException e) {
            LOGGER.error("POST调用【包含：httpBody】：参数运行报错为："+e.getMessage());
        }
        return result;
    }

    /**
     * restTemplate：post请求：form-data 方式
     * @param url 地址
     * @param multiValueMap 参数
     * @return 结果
     */
    public static JSONObject postForEntityFormData(String url, MultiValueMap<String, Object> multiValueMap){
        JSONObject result = null;
        try {
            LOGGER.info("postForEntityFormData:请求地址为："+url+" 参数数量为："+multiValueMap.size());
            //赋值案例：
            //MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
            //multiValueMap.add("id", 1);
            //multiValueMap.add("name", "str");
            ResponseEntity<String> responseEntity = restTemplate.postForEntity(url,multiValueMap,String.class);
            String jsonValue = responseEntity.getBody();
            if (AssertUtil.isVal(jsonValue) && JsonValid(jsonValue)) {
                result = JSONObject.parseObject(jsonValue);
            }
            if(AssertUtil.isVal(result)) {
                String outStr = cutOut(result);
                LOGGER.info("post的form-data方式得到结果："+outStr);
            }
        } catch (HttpClientErrorException e) {
            LOGGER.error("restTemplate:调用失败：服务端返回：失败状态码："+e.getStatusCode()+
                    "\n 服务端返回：失败的消息："+e.getResponseBodyAsString());
        }catch (Exception e){
            LOGGER.error("restTemplate:调用失败：错误提示为："+e.getMessage());
        }
        return result;
    }

    /**
     * restTemplate：get请求，设置httpHeaders
     */
    public static JSONObject getForHeader(String url,HttpHeaders httpHeaders) {
        JSONObject result = null;
        try {
            if(AssertUtil.isVal(httpHeaders)){
                httpHeaders.setContentType(APPLICATION_JSON);
            }
            HttpEntity<Map<String,Object>> request = new HttpEntity<>(httpHeaders);
            ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.GET,request,String.class);
            String jsonValue = exchange.getBody();
            if (AssertUtil.isVal(jsonValue) && JsonValid(jsonValue)) {
                result = JSONObject.parseObject(jsonValue);
            }
            LOGGER.info("restTemplate的get请求结果为：" + result);
        }catch (Exception e){
            LOGGER.error("getForEntityHeader请求报错："+e.getMessage());
        }
        return result;
    }

}
